#ifndef __LIB_JNAEX_H
#define __LIB_JNAEX_H

#include "config.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct jnaex_data {
    int val;
    char *str;
} jnaex_data_t;

typedef struct jnaex_chars {
    char *data;
} jnaex_chars_t;

typedef struct jnaex_double {
    int n;
    double *data;
} jnaex_double_t;

typedef struct jnaex_strings {
    int n;
    char **data;
} jnaex_strings_t;


typedef struct jnaex_data_list {
    int n;
    jnaex_data_t *data;
} jnaex_data_list_t;

typedef void (JNAEX_CALL *jnaex_callback)(const char *sessionid, void *userdata);
JNAEX_IMPORT_OR_EXPORT int JNAEX_CALL jnaex_call_with_cb(const jnaex_callback, const char *, void *);

JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_free(void *);

// ex:int
JNAEX_IMPORT_OR_EXPORT int JNAEX_CALL jnaex_double(int);

// ex:char *
JNAEX_IMPORT_OR_EXPORT jnaex_chars_t JNAEX_CALL jnaex_getchars();
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_chars_free(jnaex_chars_t);

// ex:string
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_sendstring(const char *);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_getstring(char **);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_sendstrings(const jnaex_strings_t *);
JNAEX_IMPORT_OR_EXPORT jnaex_strings_t JNAEX_CALL jnaex_getstrings();
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_cleanstrs(jnaex_strings_t);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_sendstrarrfast(const char *, int);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_getstrarrfast(char **, int *);

// ex:struct
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_sendstruct(const jnaex_data_t *);
JNAEX_IMPORT_OR_EXPORT jnaex_data_t JNAEX_CALL jnaex_getstruct();
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_updatestruct(jnaex_data_t *);
JNAEX_IMPORT_OR_EXPORT int JNAEX_CALL jnaex_countstruct(const jnaex_data_t *, int);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_getstructarr(jnaex_data_t **, int *);

// ex: double array
JNAEX_IMPORT_OR_EXPORT double JNAEX_CALL jnaex_senddoublearr(const double *, int);
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_getdoublearr(double **, int *);

// ex: double struct
JNAEX_IMPORT_OR_EXPORT double JNAEX_CALL jnaex_senddoublestruct(const jnaex_double_t *);
JNAEX_IMPORT_OR_EXPORT jnaex_double_t JNAEX_CALL jnaex_getdoublestruct();

// ex: struct list
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_senddatalist(const jnaex_data_list_t *);
JNAEX_IMPORT_OR_EXPORT jnaex_data_list_t JNAEX_CALL *jnaex_getdatalist();
JNAEX_IMPORT_OR_EXPORT void JNAEX_CALL jnaex_data_list_free(jnaex_data_list_t);

#ifdef __cplusplus
}
#endif

#endif
